﻿using System;
using System.Linq;
using System.Reflection;
using System.Data.Linq.Mapping;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;

using LeanEngine.Extensions;
using LeanEngine.Reflection;

namespace LeanEngine.Entity
{    
    /// <summary>
    /// Base class for data transfer between the layers of the application.
    /// </summary>
    /// <remarks>
    /// Requires a integer column named DataVersion on the database table.
    /// </remarks>
    [Serializable]
    [DataContract(IsReference = true)]
    public class ChangeTrackerEntity : PlainEntity, IChangeTrack
    {
        #region Declaration Members

        private object _originalState;

        #endregion

        #region Constructor Members

        /// <summary>
        /// Initialize a new instance of Core.DataTransferObject class with the data version value equals 1.
        /// </summary>
        public ChangeTrackerEntity()
        {
            this.DataVersion = 1;
        }

        #endregion

        #region PropertyInfo Members

        /// <summary>
        /// Gets or sets the number version of the current data.
        /// </summary>
        /// <remarks>
        /// Requires a integer column named DataVersion on the database table.
        /// </remarks>
        [Column(Name = "DataVersion")]
        public int DataVersion
        {
            get;
            set;
        }

        /// <summary>
        /// Gets the properties that were modified.
        /// </summary>
        public IEnumerable<MetaColumn> ChangedProperties
        {
            get
            {
                var propertyChanges = from c in MetaTableCache.GetItem(this.GetType()).ColumnsList
                                      where !object.Equals(c.GetValue(_originalState), c.GetValue(this))
                                      select c;

                return propertyChanges;
            }
        }

        /// <summary>
        /// Gets a flag indicating whether there were changes in the properties.
        /// </summary>
        public bool HasChanges
        {
            get { return _originalState == null ? false : ChangedProperties.Count().IsGreaterThan(0); }
        }

        #endregion

        #region Method Members

        /// <summary>
        /// Sets the current state of the collection as its initial state.
        /// </summary>
        public void SaveState()
        {
            this._originalState = this.MemberwiseClone();
        }

        #endregion
    }
}
